package org.lex.game.sudoku.view;

import java.util.ArrayList;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import org.lex.game.sudoku.util.table.LabelProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HistoryTableModel extends AbstractTableModel {
	private static final long serialVersionUID = -1849423482672267900L;

	private final LabelProvider<Operation> labelProvider;
	private List<Operation> historyList = new ArrayList<>();

	private List<Operation> markerList = new ArrayList<>();

	private final Logger log = LoggerFactory.getLogger(HistoryTableModel.class);

	public HistoryTableModel(LabelProvider<Operation> labelProvider) {
		this.labelProvider = labelProvider;
	}

	public void addOperation(Operation o) {
		int insertPosition = this.historyList.size();
		this.historyList.add(o);
		this.fireTableRowsInserted(insertPosition, insertPosition);
	}

	public void reset() {
		this.historyList.clear();
		this.markerList.clear();
		this.fireTableDataChanged();
	}

	public void addMarker(int rowIndex) {
		if (rowIndex < 0) {
			log.warn("error: mark row[" + rowIndex + "] not in history operations!");
		} else {
			this.markerList.add(this.historyList.get(rowIndex));
			this.fireTableRowsUpdated(rowIndex, rowIndex);
		}
	}

	public boolean isMarked(int row) {
		return this.markerList.contains(this.historyList.get(row));
	}

	public List<Operation> getHistoryOperations(int fromRow, int toRow) {
		return new ArrayList<>(this.historyList.subList(fromRow, toRow));
	}

	public void rollback(List<Operation> opList) {
		this.historyList.removeAll(opList);
		this.markerList.removeAll(opList);
		this.fireTableDataChanged();
	}

	LabelProvider<Operation> getLabelProvider() {
		return labelProvider;
	}

	public int getRowCount() {
		return this.historyList.size();
	}

	public int getColumnCount() {
		return labelProvider.getColumnCount() + 1;
	}

	public Object getValueAt(int rowIndex, int columnIndex) {
		if (0 == columnIndex) {
			return rowIndex + 1;
		} else {
			Operation o = this.historyList.get(rowIndex);
			return this.labelProvider.getColumnValue(o, columnIndex - 1);
		}
	}

	@Override
	public String getColumnName(int column) {
		if (0 == column) {
			return "#";
		} else {
			return this.labelProvider.getColumnName(column - 1);
		}
	}

	@Override
	public Class<?> getColumnClass(int columnIndex) {
		if (0 == columnIndex) {
			return Integer.class;
		} else {
			return this.labelProvider.getColumnClass(columnIndex - 1);
		}
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return false;
	}

}
